// GTY

#pragma once

#include "CoreMinimal.h"
#include "AttributeSet.h"
#include "AbilitySystemComponent.h"
#include "AuraAttributeSet.generated.h"

// 定义宏，用于简化属性的访问和设置
#define ATTRIBUTE_ACCESSORS(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_PROPERTY_GETTER(ClassName, PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_GETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_SETTER(PropertyName) \
	GAMEPLAYATTRIBUTE_VALUE_INITTER(PropertyName)

/*已被函数指针取代
DECLARE_DELEGATE_RetVal(FGameplayAttribute, FAttributeSignature);//声明一个返回值为FGameplayAttribute的委托，名为FAttributeSignatrue
	//旨在解决广播info时重复代码的问题
*/


USTRUCT()
struct FEffectProperties/*作用于 属性变化之后效果函数 的结构体*/
{
	GENERATED_BODY()

	FEffectProperties(){}// 默认构造函数

	FGameplayEffectContextHandle EffectContextHandle;// 游戏效果的上下文句柄

	UPROPERTY()
	UAbilitySystemComponent* SourceASC = nullptr;//源能力系统组件

	UPROPERTY()
	AActor* SourceAvatarActor = nullptr;//源角色的Actor

	UPROPERTY()
	AController* SourceController = nullptr;//源控制器

	UPROPERTY()
	ACharacter* SourceCharacter = nullptr;//源角色

	UPROPERTY()
	UAbilitySystemComponent* TargetASC = nullptr;//目标能力系统组件

	UPROPERTY()
	AActor* TargetAvatarActor = nullptr;//目标角色的Actor

	UPROPERTY()
	AController* TargetController = nullptr;//目标控制器

	UPROPERTY()
	ACharacter* TargetCharacter = nullptr;//目标角色
};

//typedef TBaseStaticDelegateInstance<FGameplayAttribute(),FDefaultDelegateUserPolicy>::FFuncPtr AttributeFuncPtr;//函数指针
template<class T>
using TStaticFuncPtr =typename  TBaseStaticDelegateInstance<T,FDefaultDelegateUserPolicy>::FFuncPtr;
//本质上是一个可以存放任意函数地址的函数指针           例FGameplayAttribute()


/**
 * 
 */
UCLASS()
class AURAGAME_API UAuraAttributeSet : public UAttributeSet
{
	GENERATED_BODY()
public:
	UAuraAttributeSet();

	virtual void GetLifetimeReplicatedProps(TArray<FLifetimeProperty>& OutLifetimeProps) const override;
	//网络复制，确保客户端和服务器之间的数据同步

	virtual void PreAttributeChange(const FGameplayAttribute& Attribute, float& NewValue) override;
	//游戏属性值即将改变 之前 被调用            Attribute属性、NewValue新值
	
	virtual void PostGameplayEffectExecute(const FGameplayEffectModCallbackData& Data) override;
	//游戏效果执行 之后 被调用

	virtual void PostAttributeChange(const FGameplayAttribute& Attribute, float OldValue, float NewValue) override; //属性变动后回调函数


	
	//TBaseStaticDelegateInstance<FGameplayAttribute(),FDefaultDelegateUserPolicy>::FFuncPtr FunctionPointer;//函数指针
	/*本质上是一个可以保存具有某个签名的函数变量*///泛型编程

	//下面三个等价
	TMap<FGameplayTag,	TStaticFuncPtr<FGameplayAttribute()>> TagsToAttributes;
	//TMap<FGameplayTag,TBaseStaticDelegateInstance<FGameplayAttribute(),FDefaultDelegateUserPolicy>::FFuncPtr> TagsToAttributes;
	//TMap<FGameplayTag,FGameplayAttribute(*)()> TagsToAttributes;

	
	
    /*
    * 主要属性
     */
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Strength,Category="Primary Attributes")
	FGameplayAttributeData  Strength;//力量
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Strength);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Intelligence,Category="Primary Attributes")
	FGameplayAttributeData  Intelligence;//智力
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Intelligence);
	
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Resilience,Category="Primary Attributes")
	FGameplayAttributeData  Resilience;//韧性
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Resilience);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Vigor,Category="Primary Attributes")
	FGameplayAttributeData  Vigor;//体力
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Vigor);
	
	/*
	* 次级属性
	* */

	/*
	*	MaxHealth 血量上限，基于Vigor 体力属性计算
		MaxMana 蓝量上限，基于Intelligence 智力属性
		Armor 防御，基于Resilience 韧性属性计算， 降低所受伤害
		ArmorPenetration 护甲穿透，基于Resilience 韧性属性计算，降低敌人的防御，增加暴击率
		BlockChance 格挡率 ，基于Armor 防御属性计算，增加格挡伤害概率，触发时，降低一半所受伤害
		CriticalHitChance 暴击率，基于ArmorPenetration 护甲穿透属性计算，增加触发暴击伤害的概率
		CriticalHitDamage 暴击伤害，基于ArmorPenetration 护甲穿透属性计算，触发暴击时基于增加的伤害量
		CriticalHitResistance 暴击抵抗，基于Armor 防御属性计算，降低敌人的暴击概率
		HealthRegeneration 血量自动恢复，基于Vigor 体力属性计算，每秒自动恢复一定血量
		ManaRegeneration 蓝量自动恢复，基于Intelligence 智力属性，每秒自动恢复蓝量
	 */

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Armor,Category="Secondary Attributes")
	FGameplayAttributeData  Armor;//防御
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Armor);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_ArmorPenetration,Category="Secondary Attributes")
	FGameplayAttributeData  ArmorPenetration;//护甲穿透
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, ArmorPenetration);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_BlockChance,Category="Secondary Attributes")
	FGameplayAttributeData  BlockChance;//格挡率
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, BlockChance);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_CriticalHitChance,Category="Secondary Attributes")
	FGameplayAttributeData  CriticalHitChance;//暴击率
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, CriticalHitChance);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_CriticalHitDamage,Category="Secondary Attributes")
	FGameplayAttributeData  CriticalHitDamage;//暴击伤害
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, CriticalHitDamage);
	
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_CriticalHitResistance,Category="Secondary Attributes")
	FGameplayAttributeData  CriticalHitResistance;//暴击抵抗
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, CriticalHitResistance);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_HealthRegeneration,Category="Secondary Attributes")
	FGameplayAttributeData  HealthRegeneration;//血量自动恢复
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, HealthRegeneration);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_ManaRegeneration,Category="Secondary Attributes")
	FGameplayAttributeData  ManaRegeneration;//蓝量自动恢复
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, ManaRegeneration);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_EnergyRegeneration,Category="Secondary Attributes")
	FGameplayAttributeData  EnergyRegeneration;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, EnergyRegeneration);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_MaxHealth,Category="Secondary Attributes")
	FGameplayAttributeData  MaxHealth;//最大生命值
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, MaxHealth);
	
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_MaxMana,Category="Secondary Attributes")
	FGameplayAttributeData  MaxMana;//最大法力值
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, MaxMana);

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_MaxEnergy,Category="Vital Attributes")
	FGameplayAttributeData  MaxEnergy;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, MaxEnergy);

	

	
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_FireResistance, Category="Resistance Attributes")
	FGameplayAttributeData FireResistance; // 火属性抗性
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, FireResistance);
	
	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_LightningResistance, Category="Resistance Attributes")
	FGameplayAttributeData LightningResistance; // 雷属性抗性
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, LightningResistance);

	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_ArcaneResistance, Category="Resistance Attributes")
	FGameplayAttributeData ArcaneResistance; // 魔法抗性
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, ArcaneResistance);

	UPROPERTY(BlueprintReadOnly, ReplicatedUsing = OnRep_PhysicalResistance, Category="Resistance Attributes")
	FGameplayAttributeData PhysicalResistance; // 物理抗性
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, PhysicalResistance);



	/*
	 * 重要属性
	 */
	
	/*
	 * Health：这是一个标记为ReplicatedUsing的属性，类型为FGameplayAttributeData，
	 * 表示角色的生命值。当这个属性在服务器上发生变化时，会调用OnRep_Health函数来同步客户端。
	 * 
	 *	OnRep_Health：这是一个函数，当Health属性在服务器上发生变化并同步到客户端时被调用。
	 *	参数OldHealth表示变化前的生命值。该函数通常用于处理生命值变化后的逻辑，如更新UI或触发事件。
	 */
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Health,Category="Vital Attributes")
	FGameplayAttributeData  Health;//生命值
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Health);
	/*
	ATTRIBUTE_ACCESSORS宏调用后，最终会生成四个函数，那Strength举例，会生成四个函数分别是：
	GetStrengthAttribute() 获取属性引用
	GetStrength() 获取属性值
	SetStrength(float NewValue)设置属性值
	InitStrength(float NewValue) 初始化属性值
	 */

	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Mana,Category="Vital Attributes")
	FGameplayAttributeData  Mana;//法力值
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Mana);

	//energy
	UPROPERTY(BlueprintReadOnly,ReplicatedUsing = OnRep_Energy,Category="Vital Attributes")
	FGameplayAttributeData  Energy;
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, Energy);
	



	
	/*
	 * 元属性
	 */
	UPROPERTY(BlueprintReadOnly, Category="Meta Attributes")
	FGameplayAttributeData IncomingDamage; //处理传入的伤害
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, IncomingDamage);

	UPROPERTY(BlueprintReadOnly, Category="Meta Attributes")
	FGameplayAttributeData IncomingXP; //处理传入的经验
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, IncomingXP);

	UPROPERTY(BlueprintReadOnly, Category="Meta Attributes")
	FGameplayAttributeData IncomingMoney; //处理传入的金币
	ATTRIBUTE_ACCESSORS(UAuraAttributeSet, IncomingMoney);



	
	UFUNCTION()
	void OnRep_Health(const FGameplayAttributeData& OldHealth) const;

	UFUNCTION()
	void OnRep_MaxHealth(const FGameplayAttributeData& OldMaxHealth) const;

	UFUNCTION()
	void OnRep_Mana(const FGameplayAttributeData& OldMana) const;

	UFUNCTION()
	void OnRep_MaxMana(const FGameplayAttributeData& OldMaxMana) const;

	UFUNCTION()
	void OnRep_Energy(const FGameplayAttributeData& OldEnergy) const;

	UFUNCTION()
	void OnRep_MaxEnergy(const FGameplayAttributeData& OldMaxEnergy) const;

	UFUNCTION()
	void OnRep_Strength(const FGameplayAttributeData& OldStrength) const;

	UFUNCTION()
	void OnRep_Intelligence(const FGameplayAttributeData& OldIntelligence) const;

	UFUNCTION()
	void OnRep_Resilience(const FGameplayAttributeData& OldResilience) const;

	UFUNCTION()
	void OnRep_Vigor(const FGameplayAttributeData& OldVigor) const;

	UFUNCTION()
	void OnRep_Armor(const FGameplayAttributeData& OldArmor) const;

	UFUNCTION()
	void OnRep_ArmorPenetration(const FGameplayAttributeData& OldArmorPenetration) const;

	UFUNCTION()
	void OnRep_BlockChance(const FGameplayAttributeData& OldBlockChance) const;

	UFUNCTION()
	void OnRep_CriticalHitChance(const FGameplayAttributeData& OldCriticalHitChance) const;

	UFUNCTION()
	void OnRep_CriticalHitDamage(const FGameplayAttributeData& OldCriticalHitDamage) const;

	UFUNCTION()
	void OnRep_CriticalHitResistance(const FGameplayAttributeData& OldCriticalHitResistance) const;

	UFUNCTION()
	void OnRep_HealthRegeneration(const FGameplayAttributeData& OldHealthRegeneration) const;

	UFUNCTION()
	void OnRep_ManaRegeneration(const FGameplayAttributeData& OldManaRegeneration) const;

	UFUNCTION()
	void OnRep_EnergyRegeneration(const FGameplayAttributeData& OldEnergyRegeneration) const;

	UFUNCTION()
	void OnRep_FireResistance(const FGameplayAttributeData& OldFireResistance) const;

	UFUNCTION()
	void OnRep_LightningResistance(const FGameplayAttributeData& OldLightningResistance) const;

	UFUNCTION()
	void OnRep_ArcaneResistance(const FGameplayAttributeData& OldArcaneResistance) const;

	UFUNCTION()
	void OnRep_PhysicalResistance(const FGameplayAttributeData& OldPhysicalResistance) const;




	
private:

	//处理传入的参数为伤害属性时，处理的逻辑
	void HandleIncomingDamage(const FEffectProperties& Props);

	//处理传入的参数为经验属性时，处理的逻辑
	void HandleIncomingXP(const FEffectProperties& Props);

	//如果当前伤害触发了负面效果，处理的逻辑
	void HandleDeBuff(const FEffectProperties& Props);


	
	static void SetEffectProperties(const FGameplayEffectModCallbackData& Data, FEffectProperties& Props);

	void ShowFloatingText(const FEffectProperties& Props, const float Damage, bool IsBlockedHit, bool IsCriticalHit) const;

	
	//发送经验事件
	void SendXPEvent(const FEffectProperties& Props);

	//发送金币事件
	void SendMoneyEvent(const FEffectProperties& Props);

	//将血量和蓝量填充满, 我们将设置变量
	bool bFillHealth = false;
	bool bFillMana = false;

	
};








